`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2023/12/23 20:23:05
// Design Name: 
// Module Name: tb_rv_all
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////
//`include "../source_1/new/rv_config.v"
//`include "../source_1/new/msg_config.v"
`define EBUS_ADDR_WIDTH 12
module tb_rv_all;

  // Parameters

  // Ports
  reg CLK = 0;
  reg RST = 0;
  reg EBUS_SEL = 1;
  reg EBUS_DMEM_CS = 0;
  reg EBUS_IMEM_CS = 0;
  reg EBUS_WR = 0;
  reg [`EBUS_ADDR_WIDTH-1:0] EBUS_ADDR;
  reg [127:0] EBUS_DIN;
  reg EBUS_RV_RUN = 0;
  wire [31:0] RV_FLAG;

  rv_all rv_all_dut (
    .CLK (CLK ),
    .RST (RST ),
    .EBUS_SEL (EBUS_SEL ),
    .EBUS_DMEM_CS (EBUS_DMEM_CS ),
    .EBUS_IMEM_CS (EBUS_IMEM_CS ),
    .EBUS_WR (EBUS_WR ),
    .EBUS_ADDR (EBUS_ADDR ),
    .EBUS_DIN (EBUS_DIN ),
    .EBUS_RV_RUN (EBUS_RV_RUN ),
    .RV_FLAG  ( RV_FLAG)
  );
  integer cycle=0;
  always #(5) CLK=~CLK;
  always #(10) cycle=cycle+1;
  
  task WATCH_DECODE;
    $display("RS1_INDEX=%d RS2_INDEX=%d ex_rd_index=%d ex_rd_src=%d regfile_rs1_dout=%d regfile_rs2_dout=%d DEC_RS1_VALUE=%d DEC_RS2_VALUE=%d",
        rv_all_dut.RS1_INDEX,
        rv_all_dut.RS2_INDEX,
        rv_all_dut.ex_rd_index,
        rv_all_dut.ex_rd_src,
        rv_all_dut.regfile_rs1_dout,
        rv_all_dut.regfile_rs2_dout,
        rv_all_dut.DEC_RS1_VALUE,
        rv_all_dut.DEC_RS2_VALUE);
  endtask

  task WATCH_EX;
    $display("reg1=%d, reg2=%d, Rs1=%d, Rs2=%d, Rs1_Value=%d, Rs2_Value=%d, Rd_Value=%d",
        rv_all_dut.regfile_rs1_dout,
        rv_all_dut.regfile_rs2_dout,
        rv_all_dut.RS1_INDEX,
        rv_all_dut.RS2_INDEX,
        rv_all_dut.DEC_RS1_VALUE,
        rv_all_dut.DEC_RS2_VALUE,
        rv_all_dut.EX_RD_VALUE);
  endtask;
  
  task WATCH_REG;begin
    $write("RD_INDEX=%h,RD_DIN=%h,THREAD_ADDRESS=%b,THREAD_VALUE=%h,",
        rv_all_dut.RV_REGFILE.RD_INDEX,
        rv_all_dut.RV_REGFILE.RD_DIN,
        rv_all_dut.RV_REGFILE.REGFILE.wr0_addr,
        rv_all_dut.RV_REGFILE.REGFILE.wr0_data);
    for(integer i=7'b0100000;i< 7'b1000000; i=i+1) 
        $write(" reg%d=%h ",i,rv_all_dut.RV_REGFILE.REGFILE.register_array[i]);
    $display("");
    end
  endtask;
  
  task watch_decode;
  begin
    $display("INST=%h => RS_THREAD_ID=%b, WB_DATA=%h, reg1_%d_%d=%h, reg2_%d_%d=%h",rv_all_dut.ir,rv_all_dut.RV_REGFILE.RS_THREAD_ID,rv_all_dut.RV_REGFILE.RD_DIN,rv_all_dut.RV_REGFILE.RS1_INDEX,{rv_all_dut.RV_REGFILE.RS_THREAD_ID,rv_all_dut.RV_REGFILE.RS1_INDEX},rv_all_dut.RV_REGFILE.RS1_INDEX==0?0:rv_all_dut.RV_REGFILE.RS1_DOUT,rv_all_dut.RV_REGFILE.RS2_INDEX,{rv_all_dut.RV_REGFILE.RS_THREAD_ID,rv_all_dut.RV_REGFILE.RS2_INDEX},rv_all_dut.RV_REGFILE.RS2_INDEX==0?0:rv_all_dut.RV_REGFILE.RS2_DOUT);
  end
  endtask

  task WATCH_RD_WRITE;
    if(rv_all_dut.wb_rd_index!=5'b0) 
      $display("cycle=%d thread_id=%d rd_index=%d rd=%h",
        cycle,
        rv_all_dut.wb_thread_id,
        rv_all_dut.wb_rd_index,
        rv_all_dut.wb_rd_value);
  endtask

  task WATCH_IR;
    if(rv_all_dut.decode_thread_id_valid==1'b1)
      $display("cycle=%d thread_id=%d IR=%h",
        cycle,
        rv_all_dut.decode_thread_id,
        rv_all_dut.ir,
        );
  endtask


  reg [127:0] EBUS_DATA[9:0];
  initial begin
    CLK=1'b0;
    RST=1'b0;

    #8 RST=1;
    #15 RST=0;

    //Read IMEM file to EBUS_DATA
    $readmemh("path_to_your_simulation_file",EBUS_DATA);

    //Write IMEM from EBUS_DATA just two word(8 instructions)
    EBUS_IMEM_CS=1;
    EBUS_WR=1;
    EBUS_DIN=EBUS_DATA[0]; EBUS_ADDR=0;
    #10
    EBUS_DIN=EBUS_DATA[1]; EBUS_ADDR=1;
    #10
    EBUS_DIN=EBUS_DATA[2]; EBUS_ADDR=2;
    #10
    EBUS_DIN=EBUS_DATA[3]; EBUS_ADDR=3;
    #10
    //Start RV running
    EBUS_SEL=0;EBUS_WR=0;EBUS_RV_RUN=1;
    #10 WATCH_IR();WATCH_RD_WRITE();
    #10 WATCH_IR();WATCH_RD_WRITE();
    #10 WATCH_IR();WATCH_RD_WRITE();
    #10 WATCH_IR();WATCH_RD_WRITE();
    #10 WATCH_IR();WATCH_RD_WRITE();
    #10 WATCH_IR();WATCH_RD_WRITE();
    #10 WATCH_IR();WATCH_RD_WRITE();
    #10 WATCH_IR();WATCH_RD_WRITE();
    #10 WATCH_IR();WATCH_RD_WRITE();
    #10 WATCH_IR();WATCH_RD_WRITE();
    #10 WATCH_IR();WATCH_RD_WRITE();
    #10 WATCH_IR();WATCH_RD_WRITE();
    #10 WATCH_IR();WATCH_RD_WRITE();
    #10 WATCH_IR();WATCH_RD_WRITE();
    $finish;

  end


endmodule
